这是个好题目,很有实际需求。
/a/./b/../../c/
^^ (1)
/a/b/../../c/
^^^^ (2)
/a/../c/
^^^^ (2)
//c/
^^ (3)
/c/
^ (4)
/c
我们只需要认真分析题目给出的第二个例子,就能发现几种变换方式:
. 代表当前目录,可忽略.. 代表上一级目录,应退到前一个
/ 处// 合并为 //删除显然,我们的进退应该按照 /
来区分,这是关键。我们应该对路径字符串进行以
/ 的切割。
然后一段一段的入栈出栈。接下来,我们倒过来写,看看
/a/./b/../../c/ 入栈情况:
可分割为以下部分:
a | . | b | .. | .. | c
| character | action | stack |
|---|---|---|
| a | push | a |
| . | ignore | a |
| b | push | a b |
| .. | pop | a |
| .. | pop | |
| c | push | c |
最后将结果补充上 /
即可:/c.
整理一下逻辑:
.. ,若 stack 不为空的话,pop
操作., ..,
这三种字符,无操作,continue.注:分割后每一段字符串设为 tmp.
if (tmp == ".." && !stack.empty()) stack.pop_back();
else if (tmp == "." || tmp == ".." || tmp == "") continue;
else stack.push_back(tmp);然后将栈里面的字符串连接即可:
for (auto str : stack) { ret += "/" + str; }这里提示 C++ 中字符串分割的基本技巧:使用
istringstream, 配合
getline(iss, tmp, '/')
不多说,不超过十行。AC
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <sstream>
using std::istringstream;
class Solution {
public:
string simplifyPath(string path) {
string ret, tmp;
vector<string> stack;
for ( istringstream iss(path); getline(iss, tmp, '/'); ) {
if (tmp == ".." && !stack.empty()) stack.pop_back();
else if (tmp == "." || tmp == ".." || tmp == "") continue;
else stack.push_back(tmp);
}
for (auto str : stack) { ret += "/" + str; }
return ret.empty() ? "/" : ret;
}
};